package com.zbkj.service.service.course.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zbkj.common.constants.Constants;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.category.Category;
import com.zbkj.common.model.course.*;
import com.zbkj.common.model.finance.UserRecharge;
import com.zbkj.common.model.product.StoreProduct;
import com.zbkj.common.model.system.SystemAttachment;
import com.zbkj.common.page.CommonPage;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.request.course.CourseRequest;
import com.zbkj.common.request.course.CourseSearchRequest;
import com.zbkj.common.response.CommonResult;
import com.zbkj.common.response.course.CourseListResponse;
import com.zbkj.common.response.course.CourseListStudyLogResponse;
import com.zbkj.common.response.course.CourseResponse;
import com.zbkj.common.utils.CrmebUtil;
import com.zbkj.service.dao.CourseDao;
import com.zbkj.service.service.CategoryService;
import com.zbkj.service.service.SystemAttachmentService;
import com.zbkj.service.service.UserService;
import com.zbkj.service.service.course.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Mr.Zhang
 * @description CourseServiceImpl 接口实现
 * @date 2022-07-22
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseDao, Course> implements CourseService {

    @Resource
    private CourseDao dao;

    @Autowired
    private CourseListService courseListService;

    @Autowired
    private CourseCodeService courseCodeService;

    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    private SystemAttachmentService attachmentService;


    @Autowired
    private CategoryService categoryService;

    @Autowired
    private CourseLabelService courseLabelService;

    @Autowired
    private CourseDescriptionService courseDescriptionService;

    @Autowired
    private CourseUserService courseUserService;
    @Autowired
    private UserService userService;

    @Autowired
    private CourseListStudyLogService courseListStudyLogService;

    @Autowired
    private UserTaskService userTaskService;

    /**
     * 列表
     *
     * @param request          请求参数
     * @param pageParamRequest 分页类参数
     * @return List<Course>
     * @author Mr.Zhang
     * @since 2022-07-22
     */
    @Override
    public PageInfo<CourseResponse> getList(CourseSearchRequest request, PageParamRequest pageParamRequest) {
        List<CourseResponse> courseResponses = new ArrayList<>();
        //带 Course 类的多条件查询
        LambdaQueryWrapper<Course> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotEmpty(request.getName())) {
            lambdaQueryWrapper.like(Course::getName, request.getName());
        }

        if (request.getType() == 5) {
            lambdaQueryWrapper.eq(Course::getIsRecycle, true);
        } else {
            lambdaQueryWrapper.eq(Course::getIsRecycle, false);
        }

        List<Category> childVoListByPid = categoryService.getChildVoListByPid(request.getCateId());
        List<Integer> categoryIdList = childVoListByPid.stream().map(Category::getId).collect(Collectors.toList());
        categoryIdList.add(request.getCateId());
        if (CollectionUtil.isNotEmpty(categoryIdList) && ObjectUtil.isNotNull(request.getCateId())) {
            lambdaQueryWrapper.in(Course::getCateId, categoryIdList);
        }
        lambdaQueryWrapper.eq(Course::getIsDel, false);
        Page<Course> coursePageInfo = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());

        List<Course> courseList = dao.selectList(lambdaQueryWrapper);
        if (CollectionUtil.isEmpty(courseList)) {
            return CommonPage.copyPageInfo(coursePageInfo, CollUtil.newArrayList());
        }
        if (CollectionUtil.isEmpty(courseList)) {
            return CommonPage.copyPageInfo(coursePageInfo, courseResponses);
        }
        courseList.forEach(course -> {
            CourseResponse courseResponse = new CourseResponse();
            BeanUtil.copyProperties(course, courseResponse);
            courseResponses.add(courseResponse);
        });
        if (CollectionUtil.isNotEmpty(courseResponses)) {
            compareCourseLabels(courseResponses);
        }
        return CommonPage.copyPageInfo(coursePageInfo, courseResponses);
    }

    @Override
    public PageInfo<CourseResponse> getListFront(CourseSearchRequest request, PageParamRequest pageParamRequest) {

        List<CourseResponse> courseResponses = new ArrayList<>();
        Integer uid = userService.getUserId();
        //带 Course 类的多条件查询
        LambdaQueryWrapper<Course> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotEmpty(request.getName())) {
            lambdaQueryWrapper.like(Course::getName, request.getName());
        }

        if (request.getType() == 5) {
            lambdaQueryWrapper.eq(Course::getIsRecycle, true);
        } else {
            lambdaQueryWrapper.eq(Course::getIsRecycle, false);
        }
        lambdaQueryWrapper.eq(Course::getIsShow, true);
        List<Category> childVoListByPid = categoryService.getChildVoListByPid(request.getCateId());
        List<Integer> categoryIdList = childVoListByPid.stream().map(Category::getId).collect(Collectors.toList());
        categoryIdList.add(request.getCateId());
        if (CollectionUtil.isNotEmpty(categoryIdList) && ObjectUtil.isNotNull(request.getCateId())) {
            lambdaQueryWrapper.in(Course::getCateId, categoryIdList);
        }
        lambdaQueryWrapper.eq(Course::getIsDel, false);
        Page<Course> coursePageInfo = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());

        List<Course> courseList = dao.selectList(lambdaQueryWrapper);
        if (CollectionUtil.isEmpty(courseList)) {
            return CommonPage.copyPageInfo(coursePageInfo, CollUtil.newArrayList());
        }
        courseList.forEach(course -> {
            CourseResponse courseResponse = new CourseResponse();
            BeanUtil.copyProperties(course, courseResponse);
            if (uid > 0) {
                LambdaUpdateWrapper<CourseUser> lqw = new LambdaUpdateWrapper<>();
                lqw.eq(CourseUser::getCourseId, course.getId());
                lqw.eq(CourseUser::getUid, uid);
                //增加是否已经兑换,已经兑换的增加courseUser相关信息
                List<CourseUser> courseUsers = courseUserService.list(lqw);
                if (CollectionUtil.isNotEmpty(courseUsers)) {
                    courseResponse.setIsExchange(true);
                    courseResponse.setCourseUser(courseUsers.get(0));
                }
                courseResponse.setIsExchange(true);
            }
            courseResponses.add(courseResponse);
        });
        if (CollectionUtil.isNotEmpty(courseResponses)) {
            compareCourseLabels(courseResponses);
        }
        return CommonPage.copyPageInfo(coursePageInfo, courseResponses);
    }

    private void compareCourseLabels(List<CourseResponse> courseResponses) {
        List<Integer> courseIds = courseResponses.stream().map(CourseResponse::getId).collect(Collectors.toList());
        List<CourseLabel> courseLabels = courseLabelService.getLabelByCourseIds(courseIds);
        if (CollectionUtil.isEmpty(courseLabels))
            return;
        Map<Integer, List<CourseLabel>> labelMap = courseLabels.stream().collect(Collectors.groupingBy(CourseLabel::getCourseId));

        courseResponses.forEach(courseResponse -> {
            if (labelMap.containsKey(courseResponse.getId())) {
                courseResponse.setLabels(labelMap.get(courseResponse.getId()));
            }
        });
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<String> addCourse(CourseRequest request) {
        Course course = new Course();
        BeanUtils.copyProperties(request, course);

        course.setCreateTime(new Date());
        if (ObjectUtil.isNotEmpty(request.getImageAttId())) {
            SystemAttachment attachment = attachmentService.getById(request.getImageAttId());
            course.setImage(attachment.getSattDir());
        }
        this.save(course);
        CourseDescription courseDescription = new CourseDescription();
        courseDescription.setDescription(request.getDescription().length() > 0 ? attachmentService.clearPrefix(request.getDescription()) : "");
        courseDescription.setType(Constants.COURSE_DESCRIPTION_TYPE_COURSE);
        courseDescription.setLinkId(course.getId());
        courseDescriptionService.save(courseDescription);
        if (CollectionUtil.isNotEmpty(request.getCourseLabelList())) {
            List<CourseLabel> courseLabelList = new ArrayList<>();
            request.getCourseLabelList().forEach(courseLabel -> {
                CourseLabel label = new CourseLabel();
                BeanUtil.copyProperties(courseLabel, label);
                label.setCourseId(course.getId());
                courseLabelList.add(label);
            });
            courseLabelService.saveBatch(courseLabelList);
        }
        return CommonResult.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Map<String, Object>> updateCourse(CourseRequest request) {
        Map<String, Object> data = new HashMap<>();
//        if(ObjectUtil.isEmpty(request.getCateId())){
//            data.put("success",false);
//            data.put("message","分类id不能为空");
//            return CommonResult.success(data);
//        }
        Course course = new Course();
        BeanUtils.copyProperties(request, course);
        if (ObjectUtil.isNotEmpty(request.getImageAttId())) {
            SystemAttachment attachment = attachmentService.getById(request.getImageAttId());
            course.setImage(attachment.getSattDir());
        }
        this.updateById(course);
        //删除标签
        LambdaQueryWrapper<CourseLabel> cdluw = new LambdaQueryWrapper<>();
        cdluw.eq(CourseLabel::getCourseId, request.getId());
        courseLabelService.remove(cdluw);
        //新增标签
        if (CollectionUtil.isNotEmpty(request.getCourseLabelList())) {
            List<CourseLabel> courseLabelList = new ArrayList<>();
            request.getCourseLabelList().forEach(courseLabel -> {
                CourseLabel label = new CourseLabel();
                BeanUtil.copyProperties(courseLabel, label);
                label.setCourseId(course.getId());
                courseLabelList.add(label);
            });
            courseLabelService.saveBatch(courseLabelList);
        }
        //详情富文本处理
        CourseDescription courseDescription = new CourseDescription();
        courseDescription.setDescription(request.getDescription().length() > 0 ? attachmentService.clearPrefix(request.getDescription()) : "");
        courseDescription.setType(Constants.COURSE_DESCRIPTION_TYPE_COURSE);
        courseDescription.setLinkId(course.getId());

        courseDescriptionService.deleteById(Constants.COURSE_DESCRIPTION_TYPE_COURSE, course.getId());
        courseDescriptionService.save(courseDescription);


        data.put("success", true);
        return CommonResult.success(data);
    }

    @Override
    public CommonResult<Map<String, Object>> onlineOff(Integer id, Boolean isShow) {
        Map<String, Object> data = new HashMap<>();
        LambdaUpdateWrapper<Course> uqw = new LambdaUpdateWrapper<>();
        uqw.eq(Course::getId, id);
        uqw.set(Course::getIsShow, isShow);
        this.update(uqw);
        data.put("success", true);
        return CommonResult.success(data);
    }

    @Override
    public CourseResponse detail(Integer id) {
        Course course = this.getById(id);
        //获取课程目录
        LambdaQueryWrapper<CourseList> courseListLambdaQueryWrapper = new LambdaQueryWrapper<>();
        courseListLambdaQueryWrapper.eq(CourseList::getCourseId, id);
        List<CourseList> courseLists = courseListService.list(courseListLambdaQueryWrapper);
        CourseResponse courseResponse = new CourseResponse();
        BeanUtil.copyProperties(course, courseResponse);
        List<CourseListResponse> courseListResponses = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(courseLists)) {
            courseLists.forEach(courseList -> {
                CourseListResponse courseListResponse = new CourseListResponse();
                BeanUtil.copyProperties(courseList, courseListResponse);
                courseListResponses.add(courseListResponse);
            });
        }
        courseResponse.setCourseLists(courseListResponses);

        // 增加课程码的获取

        LambdaQueryWrapper<CourseCode> courseCodeQuery = new LambdaQueryWrapper<>();
        courseCodeQuery.eq(CourseCode::getCourseId, id);
        courseCodeQuery.last("limit 10");
        List<CourseCode> courseCodes = courseCodeService.list(courseCodeQuery);
        if (CollectionUtil.isNotEmpty(courseCodes)) {
            courseResponse.setCourseCodeList(courseCodes);
        }
        courseResponse.setLabels(courseLabelService.getLabelByCourseId(id));

        //获取富文本详情
        LambdaQueryWrapper<CourseDescription> dlqw = new LambdaQueryWrapper<>();
        dlqw.eq(CourseDescription::getLinkId, id);
        dlqw.eq(CourseDescription::getType, Constants.COURSE_DESCRIPTION_TYPE_COURSE);
        List<CourseDescription> courseDescriptions = courseDescriptionService.list(dlqw);
        if (CollectionUtil.isNotEmpty(courseDescriptions)) {
            courseResponse.setDescription(StrUtil.isBlank(courseDescriptions.get(0).getDescription()) ? "" : courseDescriptions.get(0).getDescription());
        }
        return courseResponse;
    }

    @Override
    public CourseResponse detailFront(Integer id) {
        Integer uid = userService.getUserId();
        Course course = this.getById(id);
        //获取课程目录
        LambdaQueryWrapper<CourseList> courseListLambdaQueryWrapper = new LambdaQueryWrapper<>();
        courseListLambdaQueryWrapper.eq(CourseList::getCourseId, id);
        List<CourseList> courseLists = courseListService.list(courseListLambdaQueryWrapper);
        CourseResponse courseResponse = new CourseResponse();
        BeanUtil.copyProperties(course, courseResponse);
        //获取富文本详情
        LambdaQueryWrapper<CourseDescription> dlqw = new LambdaQueryWrapper<>();
        dlqw.eq(CourseDescription::getLinkId, id);
        dlqw.eq(CourseDescription::getType, Constants.COURSE_DESCRIPTION_TYPE_COURSE);
        List<CourseDescription> courseDescriptions = courseDescriptionService.list(dlqw);
        if (CollectionUtil.isNotEmpty(courseDescriptions)) {
            courseResponse.setDescription(StrUtil.isBlank(courseDescriptions.get(0).getDescription()) ? "" : courseDescriptions.get(0).getDescription());
        }
        //登录用户 获取其课程章节的个人信息：学习进度等
        if (uid.equals(0)) {
            List<CourseListResponse> courseListResponses = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(courseLists)) {
                courseLists.forEach(courseList -> {
                    CourseListResponse courseListResponse = new CourseListResponse();
                    BeanUtil.copyProperties(courseList, courseListResponse);
                    courseListResponses.add(courseListResponse);
                });
            }
            courseResponse.setCourseLists(courseListResponses);
            return courseResponse;
        }
        //增加用户兑换课程信息
        LambdaUpdateWrapper<CourseUser> lqw = new LambdaUpdateWrapper<>();
        lqw.eq(CourseUser::getCourseId, course.getId());
        lqw.eq(CourseUser::getUid, uid);
        //增加是否已经兑换,已经兑换的增加courseUser相关信息
        List<CourseUser> courseUsers = courseUserService.list(lqw);
        if (CollectionUtil.isNotEmpty(courseUsers)) {
            courseResponse.setIsExchange(true);
            courseResponse.setCourseUser(courseUsers.get(0));
        }
        //增加更具用户信息获取课程详情中章节的学习进度，如果没有学习记录就创建对应的学习记录
        courseResponse.setCourseLists(sycnCourseList(id, uid, courseLists));
        courseResponse.setLabels(courseLabelService.getLabelByCourseId(id));
        courseResponse.setIsExchange(true);
        return courseResponse;
    }

    private List<CourseListResponse> sycnCourseList(Integer courseId, Integer uid, List<CourseList> courseLists) {
        List<CourseListResponse> courseListResponses = new ArrayList<>();

        LambdaQueryWrapper<CourseCode> culqw = new LambdaQueryWrapper<>();
        culqw.eq(CourseCode::getUid, uid);
        culqw.eq(CourseCode::getCourseId, courseId);
        //没有兑换该课程
        if (CollectionUtil.isEmpty(courseCodeService.list(culqw))) {
            courseLists.forEach(courseList -> {
                CourseListResponse courseListResponse = new CourseListResponse();
                BeanUtil.copyProperties(courseList, courseListResponse);
                courseListResponses.add(courseListResponse);
            });
            return courseListResponses;
        }
        LambdaQueryWrapper<CourseListStudyLog> logLambdaQueryWrapper = new LambdaQueryWrapper<>();
        logLambdaQueryWrapper.eq(CourseListStudyLog::getCourseId, courseId);
        logLambdaQueryWrapper.eq(CourseListStudyLog::getUid, uid);
        List<CourseListStudyLog> courseListStudyLogs = courseListStudyLogService.list(logLambdaQueryWrapper);
        Map<Integer, CourseListStudyLog> courseListStudyLogMap = new HashMap<>();
        List<CourseListStudyLog> addLogs = new ArrayList<>();//如果课程新增了章节，则要添加学习的课程目录的记录

        if (CollectionUtil.isNotEmpty(courseListStudyLogs)) {
            courseListStudyLogMap = courseListStudyLogs.stream().collect(Collectors.toMap(CourseListStudyLog::getCourseListId, t -> t));
            for (CourseList courseList : courseLists) {
                if (!courseListStudyLogMap.containsKey(courseList.getId())) {
                    CourseListStudyLog studyLog = new CourseListStudyLog();
                    BeanUtil.copyProperties(courseList, studyLog);
                    studyLog.setUid(userService.getUserIdException());
                    studyLog.setCourseListId(courseList.getId());
                    studyLog.setId(null);
                    studyLog.setStatus(0);//订单状态（0：未学习；1：学习中；2：已完成）
                    studyLog.setCreateTime(new Date());
                    studyLog.setUpdateTime(null);
                    addLogs.add(studyLog);
                }
            }
        } else {
            //
            courseLists.forEach(courseList -> {
                CourseListStudyLog studyLog = new CourseListStudyLog();
                BeanUtil.copyProperties(courseList, studyLog);
                studyLog.setUid(userService.getUserIdException());
                studyLog.setCourseListId(courseList.getId());
                studyLog.setId(null);
                studyLog.setStatus(0);//订单状态（0：未学习；1：学习中；2：已完成）
                studyLog.setCreateTime(new Date());
                studyLog.setUpdateTime(null);
                addLogs.add(studyLog);
            });
        }
        courseListStudyLogService.saveBatch(addLogs);

        courseListStudyLogs = courseListStudyLogService.list(logLambdaQueryWrapper);
        Map<Integer, CourseListStudyLog> studyLogMapMap = courseListStudyLogs.stream().collect(Collectors.toMap(CourseListStudyLog::getCourseListId, t -> t));
        courseLists.forEach(courseList -> {
            CourseListStudyLog courseListStudyLog = studyLogMapMap.get(courseList.getId());
            CourseListResponse courseListResponse = new CourseListResponse();
            BeanUtil.copyProperties(courseList, courseListResponse);
            courseListResponse.setStudyLength(courseListStudyLog.getStudyLength());
            courseListResponse.setUid(courseListStudyLog.getUid());
            courseListResponse.setStatus(courseListStudyLog.getStatus());
            courseListResponse.setPlayCount(courseList.getPlayCount());
            courseListResponse.setCourseListStudyLogId(courseListStudyLog.getId());
            courseListResponses.add(courseListResponse);
        });

        return courseListResponses;
    }

    @Override
    public CommonResult<String> deleteCourse(Integer id, String type) {
        Course course = getById(id);
        if (ObjectUtil.isNull(course)) {
            throw new CrmebException("课程不存在");
        }
        if (StrUtil.isNotBlank(type) && "recycle".equals(type) && course.getIsDel()) {
            throw new CrmebException("课程已存在回收站");
        }
        LambdaUpdateWrapper<Course> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        if (StrUtil.isNotBlank(type) && "delete".equals(type)) {
            lambdaUpdateWrapper.eq(Course::getId, id);
            lambdaUpdateWrapper.set(Course::getIsDel, true);
            return CommonResult.success(update(lambdaUpdateWrapper) + "");
        }
        lambdaUpdateWrapper.eq(Course::getId, id);
        lambdaUpdateWrapper.set(Course::getIsRecycle, true);
        return CommonResult.success(update(lambdaUpdateWrapper) + "");
    }

    @Override
    public CommonResult<String> addPlayTime(Integer courseId, Integer courseListId) {

        LambdaUpdateWrapper<Course> cluw = new LambdaUpdateWrapper<>();
        cluw.eq(Course::getId, courseId);
        cluw.setSql(StrUtil.format("play_count = play_count + {}", 1));
        this.update(cluw);
        LambdaUpdateWrapper<CourseList> clluw = new LambdaUpdateWrapper<>();
        clluw.eq(CourseList::getId, courseListId);
        clluw.setSql(StrUtil.format("play_count = play_count + {}", 1));
        courseListService.update(clluw);
//        userTaskService.completeTask(1);//视频观看任务获得积分
        return CommonResult.success();
    }


}

